import numpy as np
import os
import math
import random
import time
import hashlib
from typing import Union
# np.random.seed(55)


# 指数分布函数1 / lamda是均值
def get_time_with_exponent( lamda):
    return np.random.exponential(scale=1 / lamda, size=(1, 1))[0, 0]

def get_reliability_without_failure(duration, lambda_t):
    reliability=math.exp(-1*duration*lambda_t)
    return reliability

def get_aim_replica_num(aim_reliability, single_reliability):
    aim_replica_num=1
    while 1-(1-single_reliability)**aim_replica_num <aim_reliability:
        aim_replica_num+=1
    return aim_replica_num

def get_root_dir():
    cur_dir = os.path.dirname(os.path.abspath(__file__))
    root_dir = os.path.dirname(cur_dir)
    return root_dir

def get_out_dir():
    cur_dir = os.path.dirname(os.path.abspath(__file__))
    out_dir = cur_dir+"/output"
    return out_dir

def get_cur_dir():
    cur_dir = os.path.dirname(os.path.abspath(__file__))
    return cur_dir
def get_dataset_dir():
    return "/root/autodl-tmp/CallGraph_dataset"

def list_is_sub_of_another_list(list_sub, list_full):
    for ele in list_sub:
        if ele not in list_full:
            return False
    return True

def ensure_directory_exists(full_path):
    
    # 检查文件夹是否存在
    if not os.path.exists(full_path):
        try:
            # 创建文件夹（包括父目录）
            os.makedirs(full_path, exist_ok=True)
            # print(f"文件夹已创建: {full_path}")
        except OSError as e:
            print(f"创建文件夹失败: {e} path:{full_path}")
            exit(-1)
            return None
    # else:
        
    #     print(f"文件夹已存在: {full_path}")
    
    return full_path

def _seed_from_string(s: str) -> int:
    """从字符串生成稳定的整数种子（跨进程/跨运行一致）。"""
    h = hashlib.sha256(s.encode("utf-8")).digest()
    return int.from_bytes(h, "big")

def stable_random_by_key(key: str, min_value: Union[int, float], max_value: Union[int, float]):
    """
    基于字符串 key 生成可重复的“随机”数：
    - 若 min/max 都为 int，返回 int（闭区间 [min, max]）
    - 否则返回 float（闭区间 [min, max]）
    """
    if min_value > max_value:
        min_value, max_value = max_value, min_value  # 自动纠正区间顺序

    seed = _seed_from_string(key)
    rng = random.Random(seed)  # 局部 RNG，不影响全局随机状态
    return rng.randint(min_value, max_value)

class Args:
    def __init__(self,para=None):
        if para==None:
            self.init_with_default()
        else:

            self.init_with_paras(para)

    def init_with_default(self):
        self.deploy_schedule_strategy = "ours"
        self.priority_queue=False
        self.state_resource_percent=0.3
        self.aim_service_name=None
        self.bare_metal_node_num=100
        self.high_frequency_N=0
        self.heuristic_replica="up_deal_time"
        self.heuristic_deploy="time_cover"
        self.jump_request_num=0
        self.elastic_deploy=True  #用于消融实验
        self.deploy_para=0.6
        self.pre_deploy=True
        self.dynamic_replica=True
        #负载设置
        self.request_num=1
        self.pre_request_num=0
        self.trace_id=0
        self.time_expand=0.1
        self.no_cut_time_in_queue=1000
        ########################################
        #动态比例范围(大的包含，小的不包含)
        self.dynamic_percent_min=0
        self.dynamic_percent_max=1
        #分区比例范围(大的包含，小的不包含)
        self.part_percent_min=0
        self.part_percent_max=1
        #call graph 规模(大的包含，小的不包含)
        self.call_graph_size_min=0
        self.call_graph_size_max=99999
        ########################################
        #随机数种子
        self.random_seed_for_general=10
        self.random_seed_for_resource=10
        
        #deadline需求设置
        self.deadline_factor=0.025
        #指定所有的可靠性
        self.spec_reliability=0
        self.min_reliability=0.95
        self.max_reliability=0.9999
        #泊松分布参数设置
        self.min_lambda_transient_ms=0.0001/3600000   #1/30/3600000+
        self.max_lambda_transient_ms=0.001/3600000    #1/3600000+
        #微服务调用成本设置
        self.min_ms_kind_cost=0.06
        self.max_ms_kind_cost=0.9
        #带宽设置
        self.ave_bandwidth=20*1024*1024/1000  #20MBps
        #仿真时间设置
        self.until_time=0
        #输出设置
        self.print_level=0
        self.outfile_flage=True
        
        # self.GSMS_init_deploy_flage=False
        
        self.out_dir="output"
        self.aim_service_file=get_root_dir()+"/data_process/dealed_data/statistic_pkl_sift_dataset_0d11_0d12.csv"
        self.history_base_file=get_root_dir()+"/data_process/dealed_data/dataset_0d11_0d12.base"
        # self.validate_trace_file=get_root_dir()+"/data_process/dealed_data/CallGraph_dataset_0d12_0d13_cleaned_0.5_s1_validate.csv"
        
        return

    def init_with_paras(self,para):

        return